import math
import plistlib
import os
from tkinter import messagebox
from PIL import Image, ImageTk
import tkinter as tk
from tkinter import filedialog, Entry, Button, StringVar


def create_window(parent=None):
    global offX, offY
    offX = 60
    offY = 50

    # 裁剪图片边界区域
    global left_value, right_value, up_value, down_value
    left_value = 1
    right_value = 1
    up_value = 1
    down_value = 1

    global imgs_scale,imgs_Dic,dirName_Dic,scale_value, scale_index,cur_directory_type_index
    cur_directory_type_index = 0
    scale_value = 1
    imgs_Dic = {}
    dirName_Dic={}
    imgs_scale = []
    scale_index = 0

    # 创建窗口
    if parent is None:
        root = tk.Tk()
    else:
        root = tk.Toplevel(parent)
    root.title("以固定尺寸切割plist")
    root.config(bg="grey")
    root.geometry("1000x1000+0+0")

    # 图像绘制位置坐标
    canvas = tk.Canvas(root, width=800, height=800, bg="gray")
    canvas.place(x=offX + 70, y=offY + 130)
    def select_directory(entry_var):
        """弹出选择目录对话框"""
        directory = filedialog.askdirectory(parent=root)
        entry_var.set(directory)
        root.lift()
    # 第一行：按钮+输入框
    entry_scale_frame_path = StringVar()
    entry_path = Entry(root, textvariable=entry_scale_frame_path)
    entry_path.place(x=offX + 350, y=offY - 35)
    button1 = Button(root, text="输入目录", command=lambda: select_directory(entry_scale_frame_path),
                     bg='skyblue')
    button1.place(x=offX + 500, y=offY -35)

    entry_scale_out_path = StringVar()
    entry_path = Entry(root, textvariable=entry_scale_out_path)
    entry_path.place(x=offX + 350, y=offY + 2)
    button1 = Button(root, text="输出目录", command=lambda: select_directory(entry_scale_out_path),
                     bg='skyblue')
    button1.place(x=offX + 500, y=offY +2)

    # 第二行：输入框
    tk.Label(root, text="请输入高度", bg='green').place(x=offX + 350, y=offY + 35)
    entry_scale_width = StringVar()
    entry_path1 = Entry(root, textvariable=entry_scale_width)
    entry_path1.place(x=offX + 420, y=offY + 35)

    # 第三行：输入框
    tk.Label(root, text="请输入宽度", bg='green').place(x=offX + 350, y=offY + 65)
    entry_scale_height = StringVar()
    entry_path1 = Entry(root, textvariable=entry_scale_height)
    entry_path1.place(x=offX + 420, y=offY + 65)

    def btn_last_directory():
        global cur_directory_type_index, scale_index
        if cur_directory_type_index <= 0:
            messagebox.showerror("Error", "没有了")
            return
        cur_directory_type_index -= 1
        scale_index = 0

    def btn_next_directory():
        global cur_directory_type_index, scale_index
        if cur_directory_type_index >= len(imgs_Dic) - 1:
            messagebox.showerror("Error", "没有了")
            return
        cur_directory_type_index += 1
        scale_index = 0
    def get_frame_info(frame_str):
        inner_str = frame_str[2:-2]  # 结果是 '0,277},{272,181'
        print(inner_str)
        first_brace_end_index = inner_str.find('}')
        part_1 = inner_str[:first_brace_end_index + 1]
        part_1 = part_1.rstrip('}')
        second_part_start_index = inner_str.find(',', first_brace_end_index) + 1
        part_2 = inner_str[second_part_start_index:].strip('{},')

        offset_parts_1 = part_1.split(',')
        part_frame_1_x = int(offset_parts_1[0])
        part_frame_1_y = int(offset_parts_1[1])
        print(f"Image1:{part_frame_1_x}")
        print(f"Image2:{part_frame_1_y}")

        offset_parts_2 = part_2.split(',')
        part_frame_2_x = int(offset_parts_2[0])
        part_frame_2_y = int(offset_parts_2[1])
        print(f"Image3:{part_frame_2_x}")
        print(f"Image4:{part_frame_2_y}")
        return (part_frame_1_x, part_frame_1_y, part_frame_2_x, part_frame_2_y)

    def get_rotated(isrotate):
        rotate = bool(isrotate)
        return rotate

    def getDicValue(offset_str):
        offset_parts = offset_str[1:-1].split(',')
        if int(offset_parts[0]) >= 0:
            offset_x = abs(int(offset_parts[0]))
            offset_y = abs(int(offset_parts[1]))
        else:
            offset_x = -abs(int(offset_parts[0]))
            offset_y = -abs(int(offset_parts[1]))
        return (offset_x, offset_y)

    def loadDire():
        png_frames_info = {}
        png_file_path = []
        png_full_path = ""
        png_info = {}
        sub_dir_path = ""
        plist_path=entry_scale_frame_path.get()
        output_dir=entry_scale_out_path.get()
        index = 0
        for sub_dir in os.listdir(plist_path):
            cur_frames_info = {}
            if sub_dir.endswith(".png"):
                png_full_path = os.path.join(plist_path, sub_dir)
                png_file_path.append(png_full_path)
                sub_dir_path = sub_dir
            if sub_dir.endswith(".plist"):
                # 读取 plist 文件
                plist_full_path = os.path.join(plist_path, sub_dir)
                with open(plist_full_path, 'rb') as fp:
                    plist_data = plistlib.load(fp)

                    frames_dict = plist_data.get('frames', {})

                    for png_name, frame_info in frames_dict.items():
                        # 将帧信息存储到字典中，以.png文件名作为键
                        cur_frames_info[png_name] = frame_info
                    png_info[index] = cur_frames_info
                    index += 1
        i = 0
        for png_path in png_file_path:
            num = 0
            print(png_path)
            image_atlas = Image.open(png_path)

            for png_name, frame_info in png_info[i].items():
                print(f"Image: {png_name}")
                print(f"  Frame: {frame_info['frame']}")
                print()
                frame_info_1_x, frame_info_1_y, sizeW, sizeH = get_frame_info(frame_info['frame'])
                offset_x, offset_y = getDicValue(frame_info['offset'])
                sourceSize_x, sourceSize_y = getDicValue(frame_info['sourceSize'])
                rotated_value = get_rotated(frame_info['rotated'])
                back_image = Image.new("RGBA", (int(entry_scale_width.get()), int(entry_scale_height.get())))
                back_width, back_height = back_image.size
                # 旋转处理
                if rotated_value == True:
                    new_image = image_atlas.crop(
                        (frame_info_1_x, frame_info_1_y, frame_info_1_x + sizeH, frame_info_1_y + sizeW))
                    new_image = new_image.transpose(Image.ROTATE_90)
                else:
                    new_image = image_atlas.crop(
                        (frame_info_1_x, frame_info_1_y, frame_info_1_x + sizeW, frame_info_1_y + sizeH))
                back_image.paste(new_image, (int(back_width / 2) + offset_x - 24, int(back_height / 2) + offset_y - 18))
                # 创建输出子目录
                # 1. 提取文件名
                file_name = os.path.basename(png_path)

                # 2. 去掉后缀
                base_name = os.path.splitext(file_name)[0]
                output_sub_dir = os.path.join(output_dir, base_name)
                if not os.path.exists(output_sub_dir):
                    os.makedirs(output_sub_dir)
                num += 1
                output_path = os.path.join(output_sub_dir, f"{num:2d}.png")
                print(output_path)
                back_image.save(output_path)
            i += 1
    def cur_loadDire():
        png_frames_info = {}
        png_file_path = []
        png_full_path = ""
        png_info = {}
        sub_dir_path = ""
        plist_path=entry_scale_frame_path.get()
        output_dir=entry_scale_out_path.get()
        index = 0
        for sub_dir in os.listdir(plist_path):
            cur_frames_info = {}
            if sub_dir.endswith(".png"):
                png_full_path = os.path.join(plist_path, sub_dir)
                png_file_path.append(png_full_path)
                sub_dir_path = sub_dir
            if sub_dir.endswith(".plist"):
                # 读取 plist 文件
                plist_full_path = os.path.join(plist_path, sub_dir)
                with open(plist_full_path, 'rb') as fp:
                    plist_data = plistlib.load(fp)

                    frames_dict = plist_data.get('frames', {})

                    for png_name, frame_info in frames_dict.items():
                        # 将帧信息存储到字典中，以.png文件名作为键
                        cur_frames_info[png_name] = frame_info
                    png_info[index] = cur_frames_info
                    index += 1
        image_atlas = Image.open(dirName_Dic[cur_directory_type_index])
        num = 0
        for png_name, frame_info in png_info[cur_directory_type_index].items():
            print(f"Image: {png_name}")
            print(f"  Frame: {frame_info['frame']}")
            print()
            frame_info_1_x, frame_info_1_y, sizeW, sizeH = get_frame_info(frame_info['frame'])
            offset_x, offset_y = getDicValue(frame_info['offset'])
            sourceSize_x, sourceSize_y = getDicValue(frame_info['sourceSize'])
            rotated_value = get_rotated(frame_info['rotated'])
            back_image = Image.new("RGBA", (int(entry_scale_width.get()), int(entry_scale_height.get())))
            back_width, back_height = back_image.size
            # 旋转处理
            if rotated_value == True:
                new_image = image_atlas.crop(
                    (frame_info_1_x, frame_info_1_y, frame_info_1_x + sizeH, frame_info_1_y + sizeW))
                new_image = new_image.transpose(Image.ROTATE_90)
            else:
                new_image = image_atlas.crop(
                    (frame_info_1_x, frame_info_1_y, frame_info_1_x + sizeW, frame_info_1_y + sizeH))
            back_image.paste(new_image, (int(back_width / 2) + offset_x - 24, int(back_height / 2) + offset_y - 18))
            # 创建输出子目录
            # 1. 提取文件名
            file_name = os.path.basename(dirName_Dic[cur_directory_type_index])

            # 2. 去掉后缀
            base_name = os.path.splitext(file_name)[0]
            output_sub_dir = os.path.join(output_dir, base_name)
            if not os.path.exists(output_sub_dir):
                os.makedirs(output_sub_dir)
            num += 1
            output_path = os.path.join(output_sub_dir, f"{num:2d}.png")
            print(output_path)
            back_image.save(output_path)
    def preview_images():
        global cur_directory_type_index
        cur_directory_type_index = 0
        plist_path = entry_scale_frame_path.get()
        png_frames_info = {}
        png_file_path = []
        png_info= {}
        png_full_path = ""

        sub_dir_path = ""
        index=0
        for sub_dir in os.listdir(plist_path):
            cur_frames_info= {}
            if sub_dir.endswith(".png"):
                png_full_path = os.path.join(plist_path, sub_dir)
                png_file_path.append(png_full_path)
                sub_dir_path = sub_dir
            if sub_dir.endswith(".plist"):
                # 读取 plist 文件
                plist_full_path = os.path.join(plist_path, sub_dir)
                with open(plist_full_path, 'rb') as fp:
                    plist_data = plistlib.load(fp)

                    frames_dict = plist_data.get('frames', {})

                    for png_name, frame_info in frames_dict.items():
                        # 将帧信息存储到字典中，以.png文件名作为键
                        cur_frames_info[png_name] = frame_info
                    png_info[index]=cur_frames_info
                    index+=1
        i = 0
        for png_path in png_file_path:
            cur_img = []
            image_atlas = Image.open(png_path)
            # 1. 提取文件名
            file_name = os.path.basename(png_path)
            # 2. 去掉后缀
            base_name = os.path.splitext(file_name)[0]
            base_name = png_path
            dirName_Dic[i] = base_name
            for png_name, frame_info in png_info[i].items():
                print(f"Image: {png_name}")
                print(f"base_name: {png_name}")
                print(f"  Frame: {frame_info['frame']}")
                offset_x, offset_y = getDicValue(frame_info['offset'])
                frame_info_1_x, frame_info_1_y, sizeW, sizeH = get_frame_info(frame_info['frame'])
                rotated_value = get_rotated(frame_info['rotated'])
                back_image = Image.new("RGBA", (int(entry_scale_width.get()), int(entry_scale_height.get())))
                back_width,back_height=back_image.size
                # 旋转处理
                if rotated_value == True:
                    new_image = image_atlas.crop(
                        (frame_info_1_x, frame_info_1_y, frame_info_1_x + sizeH, frame_info_1_y + sizeW))
                    new_image = new_image.transpose(Image.ROTATE_90)
                else:
                    new_image = image_atlas.crop(
                        (frame_info_1_x, frame_info_1_y, frame_info_1_x + sizeW, frame_info_1_y + sizeH))
                back_image.paste(new_image, (int(back_width / 2) + offset_x - 24, int(back_height / 2) + offset_y - 18))
                cur_img.append(back_image)
            i += 1
            imgs_Dic[base_name] = cur_img
            print(imgs_Dic)
        update_frame_sclae()
    # 第四行：按钮
    button1 = Button(root, text="预览", command=lambda: preview_images(),
                         bg='skyblue')
    button1.place(x=offX + 350, y=offY + 95)
    last_button = tk.Button(root, text="上一个", command=btn_last_directory)
    last_button.place(x=offX + 405, y=offY + 95)

    next_button = tk.Button(root, text="下一个", command=btn_next_directory)
    next_button.place(x=offX + 465, y=offY + 95)

    button2 = tk.Button(root, text="切割当前", command=cur_loadDire)
    button2.place(x=offX + 525, y=offY + 95)

    button2 = tk.Button(root, text="切割全部", command=loadDire)
    button2.place(x=offX + 595, y=offY + 95)

    # 刷新帧率图片
    def update_frame_sclae():
        global imgs_scale, scale_index, photo, resized_img, name, root_after2
        if cur_directory_type_index in dirName_Dic:
            canvas.delete("all")
            length = len(imgs_Dic[dirName_Dic[cur_directory_type_index]])
            img_scale = imgs_Dic[dirName_Dic[cur_directory_type_index]][scale_index]
            resize = [math.ceil(img_scale.size[0] * scale_value), math.ceil(img_scale.size[1] * scale_value)]
            resized_img = img_scale.resize(resize, Image.Resampling.LANCZOS)
            photo = ImageTk.PhotoImage(resized_img)
            x = int(photo.width() / 2)
            y = int(photo.height() / 2)

            canvas.create_rectangle(x - photo.width() / 2, y - photo.height() / 2, x + photo.width() / 2,
                                    y + photo.height() / 2, fill="white", outline="black")
            canvas.create_image(x, y, anchor=tk.CENTER, image=photo)

            scale_index = (scale_index + 1) % length  # 循环显示
        root_after2 = root.after(200, update_frame_sclae)

        # 重置窗口
        def reset_window(width, height):
            global image_max_width, image_max_height, canvas_width, canvas_height, center_x, center_y
            image_max_width = width
            image_max_height = height
            canvas_width = 1000
            canvas_height = 1000
            center_x = 0
            center_y = 0
            root_width = max(canvas_width, image_max_width)
            root_height = max(canvas_height, image_max_height)
            # 处理大图
            root.geometry(f"{root_width}x{root_height}+{0}+{0}")
            canvans_width = max(800, image_max_width)
            canvans_height = max(800, image_max_height)
            canvas.config(width=canvans_width, height=canvans_height)
            center_x = canvans_width / 2
            center_y = canvans_height / 2
    if parent is None:
        root.mainloop()

if __name__ == "__main__":
    create_window()


